package ferp.android.activities;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import ferp.android.GUI;
import ferp.android.R;
import ferp.android.activities.preferences.Preferences;
import ferp.android.dialogs.ProgressDialog;
import ferp.android.managers.ProfileManager;
import ferp.android.tasks.center.TaskTopPlayersGet;
import ferp.center.network.ResponseLeaderboardGet;
import ferp.center.network.ResponseRating;
import ferp.core.player.Profile;

import java.util.List;

/**
 * User: igorgok
 * Date: 5/14/12 5:15 PM
 */
public class Leaderboard extends Activity implements TaskTopPlayersGet.Listener,
                                                     DialogInterface.OnCancelListener
{
  public void onBeforeGet()
  {
    if (refresh != null)
      refresh.setEnabled(false);

    showDialog(PROGRESS);
  }

  public void onAfterGet(ResponseLeaderboardGet response)
  {
    GUI.tryToDismissDialog(this, PROGRESS);

    if (response != null)
      fill(response);

    if (refresh != null)
      refresh.setEnabled(true);
  }

  public void onCancel(DialogInterface dialogInterface)
  {
    task.cancel(true);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu)
  {
    // set locale (Android bug !!!)
    Preferences.setLocale(this, ProfileManager.instance(this).getCurrentProfile());

    // inflate menu
    getMenuInflater().inflate(R.menu.leaderboard, menu);

    refresh = menu.findItem(R.id.leaderboard_refresh);
    refresh.setIcon(R.drawable.ic_menu_refresh);

    return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    switch (item.getItemId())
    {
      case R.id.leaderboard_refresh:
        task = new TaskTopPlayersGet(this, ProfileManager.instance(this).getCurrentProfile(), this);
        task.execute();
        return true;

      default:
        return super.onOptionsItemSelected(item);
    }
  }

  @Override
  public void onBackPressed()
  {
    // propagate the event to parent tab host activity
    getParent().onBackPressed();
  }

  @SuppressWarnings("unchecked")
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    // initialize profile manager
    Profile profile = ProfileManager.instance(this).getCurrentProfile();
    Resources resources = getResources();

    // set correct orientation depends on if running on tablet or not
    GUI.setOrientation(this, profile);

    super.onCreate(savedInstanceState);

    Preferences.setLocale(this, profile);

    setContentView(R.layout.leaderboard);

    scroll = (ScrollView)findViewById(R.id.leaderboard_scroll);

    for (int i = 0; i < rows.length; ++i)
      rows[i] = Row.create(this, resources, i);

    // execute task
    task = new TaskTopPlayersGet(this, profile, this);
    task.execute();
  }

  @Override
  protected Dialog onCreateDialog(int id)
  {
    switch (id)
    {
      case PROGRESS:
        ProgressDialog progress = new ProgressDialog(this, this);
        progress.set(R.string.please_wait, R.string.leaderboard_progress_message);
        return progress;
    }

    return super.onCreateDialog(id);
  }

  @Override
  protected void onPrepareDialog(int id, Dialog dialog)
  {
    Preferences.setLocale(this, ProfileManager.instance(this).getCurrentProfile());

    super.onPrepareDialog(id, dialog);
  }

  private void fill(ResponseLeaderboardGet response)
  {
    final List<ResponseRating> ratings = response.list;
    final long rank = response.rank;
    Profile profile = ProfileManager.instance(this).getCurrentProfile();
    boolean inTop10 = false;

    for (int i = 0; i < TOP_10; ++i)
      if (i < ratings.size())
      {
        ResponseRating rr = ratings.get(i);
        boolean me = profile.centerId > 0 && profile.centerId == rr.profile;

        if (me)
        {
          inTop10 = true;
          scroll(i);
        }

        rows[i].show(i + 1, rr.name, rr.value, rr.games, rr.pool, me);
      }
      else
        rows[i].hide();

    // show player's place only if he is not in top 10 and has rank
    if (!inTop10 && rank != ResponseLeaderboardGet.NO_RANK)
    {
      ferp.core.game.Statistics statistics = profile.getStatistics();

      // if player's rank is 10 (zero-based) don't show ellipsis above
      if (rank > TOP_10)
        rows[Row.ELLIPSIS_ABOVE].show();
      else
        rows[Row.ELLIPSIS_ABOVE].hide();

      rows[Row.ME].show(rank + 1, profile.nickname, statistics.totalAmount, statistics.games.played, statistics.games.pool, true);
      rows[Row.ELLIPSIS_BENEATH].show();

      scroll(Row.ME);
    }
    else
      for (int i = TOP_10; i < rows.length; ++i)
        rows[i].hide();
  }

  private void scroll(final int me)
  {
    final DataRow row = (DataRow)rows[me];

    row.major.layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
    {
      @Override
      public void onGlobalLayout()
      {
        TableRow major = row.major.layout;
        int[] locationMe = new int[2];
        int[] locationScroll = new int[2];

        GUI.removeGlobalOnLayoutListener(row.major.layout, this);

        major.getLocationOnScreen(locationMe);
        scroll.getLocationOnScreen(locationScroll);

        int delta = locationMe[1] - locationScroll[1];

        //Log.debug(Log.TAG, "delta top = " + delta);

        if (delta < 0)
          scroll.scrollBy(0, delta);
        else
        {
          TableRow minor = row.minor.layout;

          TableLayout.LayoutParams lp1 = (TableLayout.LayoutParams)major.getLayoutParams();
          TableLayout.LayoutParams lp2 = (TableLayout.LayoutParams)minor.getLayoutParams();
          int bottom = locationMe[1] + major.getHeight() + lp1.topMargin + lp1.bottomMargin + minor.getHeight() + lp2.topMargin + lp2.bottomMargin;

          delta = bottom - (locationScroll[1] + scroll.getHeight());

          //Log.debug(Log.TAG, "delta bottom = " + delta);

          if (delta > 0)
            scroll.scrollBy(0, delta);
        }
      }
    });
  }

  // progress dialog id
  private static final int PROGRESS = 1;
  // top ten number
  private static final int TOP_10 = 10;

  private abstract static class Row
  {
    protected static TextView resolve(TableRow layout, int id, Typeface font, int color)
    {
      TextView tv = (TextView)layout.findViewById(id);

      tv.setTypeface(font);
      tv.setTextColor(color);

      return tv;
    }

    protected abstract void hide();

    protected void show(long place, String name, long rating, long games, long pool, boolean me) {}
    protected void show() {}

    private static final int ELLIPSIS_ABOVE   = TOP_10;
    private static final int ME               = ELLIPSIS_ABOVE + 1;
    private static final int ELLIPSIS_BENEATH = ME + 1;

    private static Row create(Leaderboard owner, Resources resources, int id)
    {
      return id == ELLIPSIS_ABOVE || id == ELLIPSIS_BENEATH ? new EllipsisRow(owner, resources, id) : new DataRow(owner, resources, id);
    }
  }

  private static final class DataRow extends Row
  {
    private abstract static class Data
    {
      protected abstract int getBackgroundResource(boolean me);

      protected void show(boolean me)
      {
        layout.setBackgroundResource(getBackgroundResource(me));
        layout.setVisibility(View.VISIBLE);
      }

      protected void hide() {layout.setVisibility(View.GONE);}

      private Data(Leaderboard owner, Resources resources, String prefix, int id)
      {
        layout = (TableRow)owner.findViewById(resources.getIdentifier(DataRow.PREFIX + prefix + id, "id", owner.getPackageName()));
      }

      protected final TableRow layout;
    }

    private static final class Major extends Data
    {
      @Override
      protected int getBackgroundResource(boolean me)
      {
        return me ? R.drawable.bg_leaderboard_row_major_me : R.drawable.bg_leaderboard_row_major;
      }

      private Major(Leaderboard owner, Resources resources, int id)
      {
        super(owner, resources, PREFIX, id);

        place  = resolve(layout, R.id.lb_place, GUI.Font.BOLD, Color.WHITE);
        name   = resolve(layout, R.id.lb_name, GUI.Font.BOLD, Color.WHITE);
        rating = resolve(layout, R.id.lb_rating, GUI.Font.BOLD, Color.WHITE);
      }

      private void show(long place, String name, long rating, boolean me)
      {
        this.place.setText(String.valueOf(place));
        this.name.setText(String.valueOf(name));
        this.rating.setText(String.valueOf(rating));

        show(me);
      }

      private static final String PREFIX = "major_";

      private final TextView place;
      private final TextView name;
      private final TextView rating;
    }

    private static final class Minor extends Data
    {
      @Override
      protected int getBackgroundResource(boolean me)
      {
        return me ? R.drawable.bg_leaderboard_row_minor_me : R.drawable.bg_leaderboard_row_minor;
      }

      private static TextView resolve(TableRow layout, int id1, int id2)
      {
        Row.resolve(layout, id1, GUI.Font.NORMAL, android.graphics.Color.WHITE);

        return Row.resolve(layout, id2, GUI.Font.NORMAL, android.graphics.Color.WHITE);
      }

      private static final String PREFIX = "minor_";

      private final TextView games;
      private final TextView pool;

      private Minor(Leaderboard owner, Resources resources, int id)
      {
        super(owner, resources, PREFIX, id);

        games = resolve(layout, R.id.lb_games, R.id.lb_games_value);
        pool  = resolve(layout, R.id.lb_pool, R.id.lb_pool_value);
      }

      private void show(long games, long pool, boolean me)
      {
        this.games.setText(String.valueOf(games));
        this.pool.setText(String.valueOf(pool));

        show(me);
      }
    }

    @Override
    protected void show(long place, String name, long rating, long games, long pool, boolean me)
    {
      major.show(place, name, rating, me);
      minor.show(games, pool, me);
    }

    @Override
    protected void hide()
    {
      major.hide();
      minor.hide();
    }

    private DataRow(Leaderboard owner, Resources resources, int id)
    {
      major = new Major(owner, resources, id);
      minor = new Minor(owner, resources, id);
    }

    private static final String PREFIX = "lb_row_";

    private final Major major;
    private final Minor minor;
  }

  private static final class EllipsisRow extends Row
  {
    @Override
    protected void show() {layout.setVisibility(View.VISIBLE);}
    @Override
    protected void hide() {layout.setVisibility(View.GONE);}

    private EllipsisRow(Leaderboard owner, Resources resources, int id)
    {
      layout = (TableRow)owner.findViewById(resources.getIdentifier(PREFIX + id, "id", owner.getPackageName()));

      resolve(layout, R.id.lb_ellipsis, GUI.Font.BOLD, Color.WHITE);
    }

    private static final String PREFIX = "lb_row_ellipsis_";

    private TableRow layout;
  }

  private MenuItem refresh;
  private TaskTopPlayersGet task;
  private Row[] rows = new Row[TOP_10 + 3];
  private ScrollView scroll;
}
